package cn.foolishbird.hamal.frame.base;


import cn.foolishbird.hamal.frame.bsassert.BsAssert;
import cn.foolishbird.hamal.frame.bsassert.info.SysInfo;
import cn.foolishbird.hamal.frame.exception.base.BaseException;
import cn.foolishbird.hamal.frame.queryParam.QueryCondition;
import cn.foolishbird.hamal.frame.queryParam.QueryOption;
import cn.foolishbird.hamal.frame.queryParam.SortEnum;
import cn.foolishbird.hamal.frame.queryParam.fieldHandler.FieldConvert;
import cn.foolishbird.hamal.frame.queryParam.handler.QueryTypeHandler;
import cn.foolishbird.hamal.frame.queryParam.handler.QueryTypeHandlerManager;
import cn.foolishbird.hamal.frame.queryParam.wrapperHandler.QueryWrapperHandler;
import cn.foolishbird.hamal.frame.queryParam.wrapperHandler.QueryWrapperHandlerManager;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Map;

/**
 * @author Eric
 * @since 2019-05-06
 */
public class CustomBaseServiceImpl<M extends BaseMapper<T>, T> extends ServiceImpl<M, T> implements CustomService<T> {

    @Resource
    protected QueryTypeHandlerManager queryTypeHandlerManager;

    @Resource
    private QueryWrapperHandlerManager queryWrapperHandlerManager;

    @Resource
    private FieldConvert<String, String> fieldConvert;

    @Override
    public T managerDetail(Long id) throws BaseException {
        return this.getById(id);
    }

    @Override
    public IPage<T> managerPage(QueryCondition condition) throws BaseException {
        return this.page(createPage(condition), pageAppendQueryWrapper(condition));
    }

    @Override
    public T managerAdd(T data) throws BaseException {
        this.save(data);
        return data;
    }

    @Override
    public T managerUpdate(T data) {
        this.updateById(data);
        return data;
    }

    @Override
    public Boolean managerDelete(Long[] ids) {
        return this.removeByIds(Arrays.asList(ids));
    }

    @Override
    public String joinConvert(Long id) {
        // todo 这里先预留着， 需要配置原数据，通过元数据转换
        return String.valueOf(id);
    }

    /**
     * @param condition
     * @return com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<T>
     * @throws
     * @author Eric
     * @date 2020/3/11
     **/
    protected QueryWrapper<T> pageAppendQueryWrapper(QueryCondition condition) {
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        if (condition.getOptions() != null) {
            for (Map.Entry<String, QueryOption> entry : condition.getOptions().entrySet()) {
                QueryOption option = entry.getValue();
                QueryTypeHandler typeHandler = queryTypeHandlerManager.obtainQueryTypeHandler(option.getFieldType());
                BsAssert.bsAssert(null == typeHandler, SysInfo.FIELD_TYPE_NOT_SUPPORT);
                // todo 考虑校验抽象 怎么加入这部分
                QueryWrapperHandler wrapperHandler = queryWrapperHandlerManager.obtainQueryWrapperHandler(option.getOptionType());
                BsAssert.bsAssert(null == typeHandler, SysInfo.WRAPPER_TYPE_NOT_SUPPORT);
                wrapperHandler.and(queryWrapper, fieldConvert.convert(option.getFieldName()), typeHandler.convert(option.getFieldValue()), typeHandler.convert(option.getFieldValueTwo()));
            }
            if (StringUtils.isNotBlank(condition.getOrderColumn())) {
                if (SortEnum.ASC.equals(condition.getOrderType())) {
                    queryWrapper.orderByAsc(fieldConvert.convert(condition.getOrderColumn()));
                } else {
                    queryWrapper.orderByDesc(fieldConvert.convert(condition.getOrderColumn()));
                }
            }
        }
        return queryWrapper;
    }

    /**
     * @param condition
     * @return com.baomidou.mybatisplus.extension.plugins.pagination.Page<T>
     * @throws
     * @author Eric
     * @date 2020/3/11
     **/
    protected Page<T> createPage(QueryCondition condition) {
        return new Page<T>(condition.getPage(), condition.getSize());
    }

}
